package com.beney.message;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.aop.framework.AopProxyUtils;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;

import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;

public class MessageHandlerContainer implements InitializingBean {

    private Logger logger = LoggerFactory.getLogger(getClass());

    // 消息类型 -> handler
    private final Map<String, MessageHandler<?>> handlers = new HashMap<>();

    // context 用于获得所有的 MessageHandler Bean
    @Autowired
    private ApplicationContext context;

    // 所有 Bean 的属性都设置完成后调用
    @Override
    public void afterPropertiesSet() throws Exception {
        // 通过接口 MessageHandler 一把获取到所有的子类 handler
        context.getBeansOfType(MessageHandler.class)
                .values()
                .forEach(handler -> handlers.put(handler.messageType(), handler));
        logger.info("[afterPropertiesSet][获取到 MessageHandler 数量: {}]", handlers.size());
    }

    /**
     * @param type 类型
     * @return MessageHandler
     */
    public MessageHandler<?> getMessageHandler(String type) {
        MessageHandler<?> handler = handlers.get(type);
        if (handler == null) {
            throw new IllegalArgumentException(String.format("类型[%s] 无法匹配到 MessageHandler", type));
        }
        return handler;
    }

    /**
     * 通过 MessageHandler 的泛型，得到消息的类型
     * TODO: 进一步测试 逻辑
     *
     * @param handler 消息处理器
     * @return 消息类型
     */
    public Class<? extends Message> getMessageClass(MessageHandler<?> handler) {
        Class<?> clazz = AopProxyUtils.ultimateTargetClass(handler);
        Type[] interfaces = clazz.getGenericInterfaces();
        Class<?> superClass = clazz.getSuperclass();
        while (0 == interfaces.length && Objects.nonNull(superClass)) {
            interfaces = superClass.getGenericInterfaces();
            superClass = clazz.getSuperclass();
        }

        for (Type type : interfaces) {
            // type 需要是泛型
            if (type instanceof ParameterizedType) {
                ParameterizedType pType = (ParameterizedType) type;
                // 需要是 MessageHandler 所携带的泛型
                if (Objects.equals(pType.getRawType(), MessageHandler.class)) {
                    Type[] actualTypeArgs = pType.getActualTypeArguments();
                    if (Objects.nonNull(actualTypeArgs) && actualTypeArgs.length > 0) {
                        return (Class<Message>) actualTypeArgs[0];
                    } else {
                        throw new IllegalStateException(String.format("类型[%s] 获取不到消息类型", handler));
                    }
                }
            }
        }
        throw new IllegalStateException(String.format("类型[%s] 获取不到消息类型", handler));
    }
}
